﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.Unity;
using SharedLib.WinFormMVCFramework;
using Tracy.DataModel;
using SharedLib;
using Tracy;


namespace TracyGUI.View.EntryTabs
{
    class TagPanel : GroupBox, ITagView
    {
        public event EventHandler<GenericEventArgs<Tag>> TagAssigning;
        public event EventHandler<GenericEventArgs<Tag>> TagRemoving;
        public event EventHandler<DataChangedEventArgs<Tag>> TagUpdating;

        public event EventHandler WillAddTag;
        public event EventHandler<GenericEventArgs<Tag>> WillUpdateTag;

        public event EventHandler<GenericEventArgs<string>> CategorySelected;

        FlowLayoutPanel _tagPanel;
        Button _btnTagAdd;
        ComboBox _cbTagCategory;
        ComboBox _cbTagValue;
        Control _editingTagControl = null;

        public TagPanel()
        {
            //Init Tag Panel
            Text = TracyFacade.Instance.LanguageManager.GetText("Tags");
            Dock = DockStyle.Fill;
            _tagPanel = new FlowLayoutPanel();
            _tagPanel.Dock = DockStyle.Fill;
            Controls.Add(_tagPanel);

            InitTagPanel();
        }

        private void InitTagPanel()
        {
            _btnTagAdd = new Button();
            _btnTagAdd.Text = TracyFacade.Instance.LanguageManager.GetText("AddTag");
            _btnTagAdd.Name = "btnAddTag";
            _btnTagAdd.Click += new EventHandler(_btnAdd_Click);

            _cbTagCategory = new ComboBox();
            _cbTagCategory.DropDownStyle = ComboBoxStyle.DropDownList;
            _cbTagCategory.SelectedIndexChanged += new EventHandler(_cbCategory_SelectedIndexChanged);

            _cbTagValue = new ComboBox();
            _cbTagValue.AutoCompleteSource = AutoCompleteSource.ListItems;
            _cbTagValue.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            _cbTagValue.KeyUp += new KeyEventHandler(_cbValue_KeyUp);

   
        }

        void _cbValue_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                foreach (string existingValue in _cbTagValue.Items)
                {
                    if (String.Equals(existingValue, _cbTagValue.Text, StringComparison.OrdinalIgnoreCase))
                    {
                        _cbTagValue.Text = existingValue; 
                        break;
                    }
                }
                ApplyTagChange();
            }
        }

        void _cbCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            string category = null;
            if (_cbTagCategory.SelectedIndex != -1)
            {
                category = _cbTagCategory.GetSelectedValue();
            }
            CategorySelected.InvokeEvent(this, new GenericEventArgs<string>(category));
        }
        
        void lbTag_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (sender is TextBox)
            {
                TextBox l = (TextBox)sender;
                Tag tag = l.Tag as Tag;
                if (tag != null)
                {
                    if (IsTagEditing()) ApplyTagChange();//Apply change before new editing
                    _editingTagControl = l;
                    l.Visible = false;
                    WillUpdateTag.InvokeEvent(this, new GenericEventArgs<Tag>(tag));
                }
            }
        }

        private void ApplyTagChange()
        {
            Tag newTag = null;
            if (!String.IsNullOrEmpty(_cbTagValue.Text))
            {
                newTag = new Tag() { Category = _cbTagCategory.GetSelectedValue(), Value = _cbTagValue.Text };
            }

            if (_editingTagControl != null && _editingTagControl.Tag != null)
            {
                Tag editingTag = (Tag)_editingTagControl.Tag;
                if (newTag == null)
                {
                    TagRemoving.InvokeEvent(this, new GenericEventArgs<Tag>(editingTag));
                }
                else if (newTag.Category != editingTag.Category || newTag.Value != editingTag.Value)
                {
                    TagUpdating.InvokeEvent(this, new DataChangedEventArgs<Tag>(editingTag, newTag));
                }
                else
                {
                    EndEditTag();
                }
            }
            else if (newTag != null)
            {
                TagAssigning.InvokeEvent(this, new GenericEventArgs<Tag>(newTag));
            }
            else
            {
                EndEditTag();
            }
        }

        private bool IsTagEditing()
        {
            return (_btnTagAdd.Name != "btnAddTag");
        }

        private void _btnAdd_Click(object sender, EventArgs e)
        {
            if (!IsTagEditing())
            {
                _editingTagControl = null;
                WillAddTag.InvokeEvent(this, e);
            }
            else
            {
                //Apply change
                ApplyTagChange();
            }
        }

        private void CreateTagControl(Tag tag, int index)
        {
            TextBox lbTag = new TextBox();
            lbTag.ReadOnly = true;
            //lbTag.BorderStyle = BorderStyle.None;
            lbTag.Text = TracyFacade.Instance.LanguageManager.GetText("TagCategory_" + tag.Category) +  ": " + tag.Value;
            lbTag.Width = 120;
            lbTag.Tag = tag;
            lbTag.MouseDoubleClick += new MouseEventHandler(lbTag_MouseDoubleClick);

            _tagPanel.Controls.Add(lbTag);
            _tagPanel.Controls.SetChildIndex(lbTag, index);
        }

        private void ShowEditControl(int index)
        {
            _tagPanel.Controls.Add(_cbTagCategory);
            _tagPanel.Controls.SetChildIndex(_cbTagCategory, index);

            //Value box
            _tagPanel.Controls.Add(_cbTagValue);
            _tagPanel.Controls.SetChildIndex(_cbTagValue, index + 1);

            if (String.IsNullOrEmpty(_cbTagValue.Text))
            {
                _cbTagValue.SelectAll();
            }
            _cbTagValue.Focus();
            //Set button index
            _btnTagAdd.Text = TracyFacade.Instance.LanguageManager.GetText("TagEditDone");
            _btnTagAdd.Name = "btnTagEditDone";
            _tagPanel.Controls.SetChildIndex(_btnTagAdd, index + 2);
        }

        #region UI Operations
        public void LoadTags(List<Tag> tags, bool clearView = true)
        {
            this.InvokeOnUIThread(() =>
            {
                if (clearView) _tagPanel.Controls.Clear();
                foreach (Tag tag in tags)
                {
                    CreateTagControl(tag, _tagPanel.Controls.Count);
                }
                if (clearView) _tagPanel.Controls.Add(_btnTagAdd);
                else _tagPanel.Controls.SetChildIndex(_btnTagAdd, _tagPanel.Controls.Count);
            });
        }

        public void RemoveTag(Tag tag)
        {
            this.InvokeOnUIThread(() =>
            {
                if (_editingTagControl != null) _tagPanel.Controls.Remove(_editingTagControl);
            });
        }

        public void UpdateTag(Tag oldTag, Tag newTag)
        {
            this.InvokeOnUIThread(() =>
            {
                if (_editingTagControl != null)
                {
                    _editingTagControl.Text = TracyFacade.Instance.LanguageManager.GetText("TagCategory_" + newTag.Category) + ": " + newTag.Value;
                    _editingTagControl.Tag = newTag;
                }
            });
        }

        public void LoadCategories(List<string> categories)
        {
            this.InvokeOnUIThread(() =>
            {
                //Setup category selection
                _cbTagCategory.Items.Clear();
                for (int i = 0; i < categories.Count; i++)
                {
                    string category = categories[i];
                    _cbTagCategory.Items.Add(new ListBoxItemValueText(category, Tracy.TracyFacade.Instance.LanguageManager.GetText("TagCategory_" + category)));
                }
            });
        }



        public void BeginAddTag(string defaultCategory)
        {
            this.InvokeOnUIThread(() =>
            {
                if (_cbTagCategory.Items.Count > 0)
                {
                    if (!String.IsNullOrEmpty(defaultCategory))
                    {
                        _cbTagCategory.SelectByValue(defaultCategory);
                        //SelectCategoryIfExists(defaultCategory);
                    }
                    else
                    {
                        _cbTagCategory.SelectedIndex = 0;
                    }
                }
                ShowEditControl(_tagPanel.Controls.Count - 1);
            });
        }

        public void BeginEditTag(Tag tag)
        {
            this.InvokeOnUIThread(() =>
            {
                _cbTagCategory.SelectByValue(tag.Category);
                _cbTagValue.Text = tag.Value;
                ShowEditControl(_tagPanel.Controls.IndexOf(_editingTagControl));
            });
        }

        public void SetRecommendedValues(List<string> values)
        {
            this.InvokeOnUIThread(() =>
            {
                _cbTagValue.Text = "";
                _cbTagValue.Items.Clear();

                foreach (string value in values) _cbTagValue.Items.Add(value);
                _cbTagValue.Focus();
            });
        }

        public void EndEditTag()
        {
            this.InvokeOnUIThread(() =>
            {
                if (_editingTagControl != null)
                {
                    _editingTagControl.Visible = true;
                }
                _tagPanel.Controls.Remove(_cbTagCategory);
                _tagPanel.Controls.Remove(_cbTagValue);
                _btnTagAdd.Text = TracyFacade.Instance.LanguageManager.GetText("AddTag");
                _btnTagAdd.Name = "btnAddTag";
                _tagPanel.Controls.SetChildIndex(_btnTagAdd, _tagPanel.Controls.Count);
            });
        }
        #endregion


    }
}
